
////////////////////////////////////////////////////////////////////////////
//	File Name: TVector.h		Last modification at : 2002-10-10 13:48:48
//	Copyright 1999-2002 Microsoft Corporation. All Rights Reserved.
//
//	Author:      Rong Xiao
//	Email :      t-rxiao@microsoft.com
//
//	Description : 
//
//	Revision History: 
//
////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __TVECTOR_H__
#define __TVECTOR_H__

#include "tmatrixdef.h"

namespace FAST
{

template <typename T> class TVector;
template <typename T> class TMatrix;
template <typename T> class TSparseVector;
template <typename T> class TSparseMatrix;

typedef TVector<float>	TFloatVector;
typedef TVector<double>	TDoubleVector;
typedef TVector<int>	TIntVector;
typedef TVector<short>	TShortVector;
typedef TVector<char>	TCharVector;
typedef TVector<unsigned int>	TUIntVector;
typedef TVector<unsigned short>	TUShortVector;
typedef TVector<unsigned char>	TByteVector;


// @class 
//   This is the template of the Vector class. It defined all kind of Vector of Vector,
//		I/O and the conversion to other types.
//
// @tcarg class | T | This is the element type of Vector
//
template <typename T>
class TVector  
{
	// @access Private Members
protected:
//***************************************************
//	Section 1:	Protected Data Members
//***************************************************

	// @cmember This is the pointer to the data buffer.
	T * m_data;

	// @cmember This is the dim of a Vector.
	int m_Dim;

    // @cmember Is the memory allocated outside of this class.
    // default False;
    bool m_IsMemoryRef;

//***************************************************
//	Section 2:	Protected Internal Functions
//***************************************************


	// Init function, only for constructor
	inline void initSize(int nDim=0) { m_data=0; m_Dim=nDim; m_IsMemoryRef=false; }
	// @access Public Members

public:

//********************************************************
//		Section 3: Memory Allocation and DeAlloc
//********************************************************/
	// @cmember This member used to Allocate the memory of Vector.
	static inline T* Allocate(int nSize)
	{
#ifdef  USE_WINALLOC
		T* ptr =(T*) GlobalAlloc(GMEM_FIXED, sizeof(T)*nSize);
#else
		T* ptr = new T[nSize];
#endif
		return ptr;
	}

	static void DestroyPtr(T*& ptr)
	{
		if( ptr != NULL )
		{
#ifdef  USE_WINALLOC
			GlobalFree(ptr);
#else
			delete [] (ptr);
#endif
			ptr = NULL;
		}
	}

	// @cmember Reallocate the memory to ajust the size of Vector
	inline T* NewSize(const int nDim, const bool bInit=true);

	// @cmember Release the memory if needed.
	inline void Destroy();	

//********************************************************
//		Section 4: Constructors and Destructors
//********************************************************/
	// @cmember Constructor
	inline TVector()	{initSize();}

	// @cmember Constructor, 
	//Defined for efficiency, the ptr will be destroyed by the destructor
	inline TVector(T* ptr, unsigned int nDim) : m_data(ptr), m_Dim(nDim), m_IsMemoryRef(false) {}

	// @cmember Constructor
	inline TVector(const int nDim) : m_IsMemoryRef(false) 
	{initSize(nDim);	m_data=Allocate(GetDim()) ;	Zero();	}

	// @cmember Constructor
	inline TVector(const int nDim, const T pval) : m_IsMemoryRef(false) {initSize(nDim); m_data=Allocate(GetDim()); Set(pval);}

	// @cmember Constructor, read data from string
	inline TVector(const int nDim, const char * valStr);

	
	// @cmember Constructor
	inline TVector(const TVector<T>& Vect);

	// @cmember Destructor
	inline ~TVector()
	{
		Destroy();
	}	
	
//*************************************************
//		Section 5: Get and set Vector properties
//*************************************************
	// @cmember Get the size of vector
	inline int GetDim() const 	{	return m_Dim;		}
    
	// @cmember Set the size of vector
	inline void SetDim(int nDim) {	assert(nDim>=0 && nDim<m_Dim ); m_Dim=nDim;	}

	// @cmember Is the memory refered outside
	inline bool SetRef(bool bIsRef=true) const
	{	TSwap(bIsRef, m_IsMemoryRef);	return bIsRef;	}

	// @cmember Is the memory refered outside
	inline bool IsRef() const
	{	return m_IsMemoryRef;		}


	// @cmember Get the buffer pointer
	inline T* GetPtr() const	{	return m_data;	}

	
//***************************************************
//	Section 6: Data Operating
//***************************************************
	/**********************************************************
		Section 6.1: Set/Get Values
	**********************************************************/

	// @cmember Set a value to all element of Vector
	inline void Set(const T val);

	// @cmember Set 0 to all element of Vector
	inline void Zero() { if ( m_data) TArrayInit(m_data,m_Dim); }

	// @cmember set an element's value,base 0
	inline void SetAt(int nDim, T NewValue);

	// @cmember get an element's value,base 0
	inline T GetAt(int nDim) const;

	// @cmember random all the element in Vector
	inline void random();

	/**********************************************************
		Section 6.2: Input and Output 
	**********************************************************/

	// It turned to global operator
		//	std::ostream& operator<<(std::ostream& s);
		//	std::istream& operator>>(std::istream& i);

	// @cmember FOR DEBUG display function for debug view , 
	//print out the Vector content in debug window
	inline void Print();
	inline int CopyData(const TVector<T>& refVect);

	// @cmember import a array for data to vector
	inline TVector<T>& ImportData(const T *pData, int nDim);
	inline TVector<T>& Array2Vect(const T *pData, int nDim, bool bRef=false);
	
	inline TVector<T>& ImportData(const std::vector<T> vect);
 	
	// @cmember write down the vector
    inline int Write(const char* szFname, bool bBinary=false) const;
    inline int Write(std::ostream& Fout, bool bBinary=false) const;

    // @cmember read the vector
    inline int Read(const char* szFname, bool bBinary=false);
    inline int Read(std::istream& Fin, bool bBinary=false);

	inline int ReadRow(const char* szMat, int iRow);
	inline int ReadRow(std::istream& Fin, int iRow);

	/*********************************************************
		Section 6.3: Type Cast operation
	*********************************************************/
	// @cmember Type convertor between difference types
	inline operator TCharVector() const;
	inline operator TShortVector() const;
	inline operator TIntVector() const;
	inline operator TByteVector() const;
	inline operator TUShortVector() const;
	inline operator TUIntVector() const;
	inline operator TFloatVector() const;
	inline operator TDoubleVector() const;
	inline operator TMatrix<T>() const;	

	/*********************************************************
		Section 6.4: Dim operation
	*********************************************************/
   	// @cmember swap Dim , base 0
	inline void SwapDim(int nDim1,int nDim2);
	inline int  DelAt(int index);
    inline TVector<T> GetSubVector(int nDimLeft, int nDim) const;
    inline int SetSubVector(TVector<T>& subVect, int nDimLeft);
	/************************************************
		Section 6.5: Is?
	************************************************/
	// @cmember Is this Vector equal zero Vector? 
	inline bool IsZero() const;

//***************************************************
//	Section 7:  OverRide Operation 
//***************************************************
	// @cmember Operator [], used to access the element of Vector
	//		This is const version, It is necessary.
	inline const T& operator[](int nDim) const ;
	
	// @cmember Operator [], used to access the element of Vector
	inline T& operator[](int nDim);

	// @cmember Operator =: Copy from another Vector
	inline TVector<T>& operator=(const TVector<T>& ref);

	// @cmember Operator =: Like <mf TVector::Set()>, set the Vector to a element.
	inline TVector<T>& operator=(const T& scale);
	
	// @cmember Vector add 
	inline TVector<T> operator+(const TVector<T>& ref) const;

	// @cmember increase all Vector elements
	inline TVector<T> operator+(const T increment) const;

	// @cmember Vector minus
	inline TVector<T> operator-(const TVector<T>& ref) const;

	// @cmember decrease all Vector elements
	inline TVector<T> operator-(const T decrement) const;

	// @cmember Vector multiple
	inline T operator*(const TVector<T>& ref) const;

	// @cmember Vector multiple
	inline TVector<T> operator*(const TMatrix<T>& ref) const;

	inline TVector<T> operator*(const TSparseMatrix<T>& ref) const { return ref.Transpose()*(*this); }	

	inline T operator*(const TSparseVector<T>& ref) const { return ref * (*this); }

	// @cmember multiple a numeric
	inline TVector<T> operator*(const T scale) const;

	// @cmember all the elements divide a numeric
	inline TVector<T> operator/(const T scale) const;
	
	// @cmember add a Vector to this Vector
	void operator+=(const TVector<T>& ref);

	// @cmember add a numeric to all the element
	void operator+=(const T incriment);

	// @cmember subtract a Vector from this Vector
	void operator-=(const TVector<T>& ref);

	// @cmember subtract a numeric from all the element
	void operator-=(const T decriment);

	// @cmember multiple a numeric to all the element
	void operator*=(const T scale);

	// @cmember multiple a matrix
	void operator*=(const TMatrix<T>& ref);

	// @cmember each elements divide a numeric
	void operator/=(const T scale);

	// @cmember Operator of equal
	inline bool operator >= (const TVector<T>& ref) const {return Compare(ref)>=0; }

	// @cmember Operator of equal
	inline bool operator > (const TVector<T>& ref) const {return Compare(ref)>0; }

	// @cmember Operator of equal
	inline bool operator < (const TVector<T>& ref) const {return Compare(ref)<0;}

	// @cmember Operator of equal
	inline bool operator <= (const TVector<T>& ref) const {return Compare(ref)<=0; }

	// @cmember Operator of equal
	inline bool operator == (const TVector<T>& ref) const;

	// @cmember Operator of equal
	inline bool operator != (const TVector<T>& ref) const { return !(*this==ref); }

	// @cmember -1 for <, 0 for ==, 1 for >
	inline int Compare (const TVector<T>& ref) const;


//************************************************
//	Section 8:	Vector Computation 
//************************************************
	inline int CountPositives() const;
	inline int CountZeros() const;
	inline int CountNegatives() const;

	// @cmember return sum of all elements
	inline double Sum(void) const;
	inline T TSum(void) const;

	// @cmember return mean of Vector
	inline double Mean(void) const;
	inline T TMean(void) const;

	// Get Descartes-Product
	inline TMatrix<T> DescartesProduct(const TVector<T>& ref) const;

	inline TVector<T> DirectProduct(const TVector<T>& ref) const;
	// Compute ABS vector
	inline TVector<T> abs(void) const;
	
   	// @cmember return 2-norm distance of two vector (in double)
	inline double GetDistance2(const TVector<T>& ref) const;
	inline T TGetDistance2(const TVector<T>& ref) const;
    
	// @cmember return the distance of two vector 
    inline double GetDistance(const TVector<T>& ref) const;

   	// @cmember Get the Variance of this vector (in double)
	inline double GetVariance(void) const;

    // @cmember return 2-norm the vector 
    inline double GetNorm2(void) const;
	inline T TGetNorm2(void) const;

    // @cmember return norm of the vector 
    inline double GetNorm(void) const;

    // @cmember set the vector norm to 1 ( or 0 for zeros )
    inline TVector<double> Normalize(void) const;

    // @cmember set the vector norm to 1 ( or 0 for zeros )
    inline TVector<T> ReScale(T tmin, T tmax) const;

	//return the value of reversed vect
	inline TVector<T> DupReverse(void) const;

	//reverse the vect
	inline TVector<T>& Reverse(void);

	//return the max value of vect
	inline T Max(void) const;

	//return the min value of vect
	inline T Min(void) const;

	//return the max value pos of vect
	inline int MaxPos(void) const;

	//return the min value pos of vect
	inline int MinPos(void) const;

	inline TVector<T>& Shuffle();
	//From the iStart, iStart+1, iEnd, select n elements, return the result index
	inline static TVector<int> RandSeq(int iStart, int iEnd, int nSel=-1) {
		int nLen=iEnd-iStart;
		if (nSel<0)		nSel=nLen;
		assert ( nLen>0 && nSel>0 );

		int* ptr=Allocate(nSel);
#ifdef FIX_RAND
		CRand utRand(20040518);
#else
		CRand utRand;
#endif
		TVector<int> index(nLen);
		for ( int i=0; i<nLen; i++) 		index[i]=i;
		
		for ( i=nLen-1; i>=nLen-nSel; i--) {
			int j=utRand.iRand(0,i);
			ptr[nLen-1-i]=index[j]+iStart;
			index[j]=index[i];
		}

		return TVector<int>(ptr,nSel);
	}
	inline TVector<T>& QSort(int iStyle=SORT_ASCENDING);

	//Do not modify the pArray contents, just update index
	inline TVector<int> QIndexSort(int iStyle=SORT_ASCENDING) const;

	//Do bubble sort nStep, the first nStep minimal element will be put ahead
	//default sort all array.
	inline TVector<T>& BubbleSort(int nStep=0, int iStyle=SORT_ASCENDING);

	//Just bubble sort the index
	inline TVector<int> BubbleIndexSort( int nStep=0, int iStyle=SORT_ASCENDING) const;

	//Required the array is sorted (ascending)
	inline int BSearch( T key, int iStyle=SORT_ASCENDING ) const;

};  //End of class TVector

template <typename T> inline std::istream & operator >> (std::istream& is, TVector<T>& vect);
template <typename T> inline std::ostream & operator << (std::ostream& os, const TVector<T>& vect);
#include "TVector.inl"

}  //End of namespace

#endif // !defined(__TVector_H__)
